home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 May: Tool Chest / Developer CD Series Tool Chest (Apple Computer)(May 1999).iso / Tool Chest / Networking / Network Watch (DMZ) v1.5 / sources / dMZMain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-25  |  37.1 KB  |  1,544 lines  |  [TEXT/MPS ]

  1. /*
  2. #-------------------------------------------------------------------------------------------
  3. #
  4. #    Program:    < DMZ 1.3 >
  5. #    File:        < dmzMain.c >
  6. #    
  7. #    by Pete Helme
  8. #    of <Apple Macintosh Developer Technical Support - or wheverever>
  9. #
  10. #    Modification History
  11. #    5/27/94     rrk    Implemented support for PPC
  12. #   2/1/94 by Peter Lovell, GE Information Services
  13. #    for Think C 6.0
  14. #    9/21/92  rrk    Implemented ATalk Trans Queue Handler
  15. #
  16. #    Copyright © 1990 Apple Computer, Inc.
  17. #    All rights reserved.
  18. #    
  19. #-------------------------------------------------------------------------------------------
  20. */
  21.  
  22. #include    "dmz.h"
  23.  
  24. #ifndef        _Gestalt
  25. #define        _Gestalt    0xA1AD
  26. #endif
  27.  
  28. #ifndef THINK_C
  29. extern _DataInit();
  30. #endif
  31.  
  32.  
  33. /*
  34.  *    imported Global Data objects, very expensive.
  35.  */
  36. extern char             gNameGlob[34];
  37. extern Boolean             gLookupFinished;
  38. extern Boolean             gUpdateListFlag;
  39. extern ListHandle         gZonesList, gObjectTypeList;
  40. extern PacketBuffer        gBuffers[kNumBuffers];
  41.  
  42.  
  43. /*
  44.  *    Global Data objects, used by routines external to main().
  45.  */
  46.  
  47.  
  48. /* 
  49.  *    gDoneFlag, becomes true when File/Quit chosen.
  50.  */
  51. Boolean        gDoneFlag;            
  52.  
  53. /* 
  54.  *    gMyDialog, our main dialog.
  55.  */
  56. DialogPtr    gMyDialog;                /* main dialog */
  57.  
  58. /* 
  59.  *    gLookupDialog, where we can set our preference for lookup times and lookup strings for
  60.  *    matching.
  61.  */
  62. DialogPtr    gLookupDialog;            /* dialog for NBP lookup prefs */
  63.  
  64. /* 
  65.  *    gSortMode is our global sort value.
  66.  */
  67. long    gSortMode;
  68.  
  69. /* 
  70.  *    gSortItem is our global sort value for which dialog item should be selected.
  71.  */
  72. short    gSortItem = kObjectID;    /* default is the object sleector */
  73.  
  74. /* 
  75.  *    gMyEvent is used for external access (from the event loop) to the event record.
  76.  *    The main outside client of this guy is use in the list routines.
  77.  */
  78. EventRecord        gMyEvent;
  79.  
  80. /* 
  81.  *    GMAC is used to hold the result of a SysEnvirons call. This makes
  82.  *    it convenient for any routine to check the environment. (What?!? no use of _Gestalt!?!? "Shuddup.")
  83.  */
  84. SysEnvRec    GMAC;                /* set up by Initialize */
  85.  
  86. /* 
  87.  *     gATalkFlags is used to track whether AppleTalk variables have been allocated, whether
  88.  *  VM is enabled, whether the transition queue handler has been installed, so that on 
  89.  *  cleanup, the appropriate actions can be taken.
  90.  */
  91. short    gATalkFlags = 0;        /* initialized right here */
  92.  
  93. /* 
  94.  *     gATQEntry is used to install an AppleTalk Transition Queue Handler so that
  95.  *     the program can handle changes to AppleTalk status.
  96.  */
  97.  
  98. myATQEntry    gATQEntry;            /* set up by Initialize */
  99.  
  100. /* 
  101.  *    gContLookUp is used as a flag to keep track of the state of whether or not we are doing
  102.  *    continuous network lookups.
  103.  */
  104. Boolean    gContLookUp = true;
  105.  
  106. /* 
  107.  *    GHasWaitNextEvent is set at startup, and tells whether the WaitNextEvent
  108.  *    trap is available. If it is false, we know that we must call GetNextEvent. 
  109.  */
  110. Boolean        gHasWaitNextEvent;    /* set up by Initialize */
  111.  
  112. /* 
  113.  *     GInBackground is maintained by our osEvent handling routines. Any part of
  114.  *     the program can check it to find out if it is currently in the background. 
  115.  */
  116. Boolean        gInBackground;        /* maintained by Initialize and DoEvent */
  117.  
  118. /* 
  119.  *     gAtalkTransUPP saves the universal procptr to the transition routine.  We only
  120.  *  want to allocate it once in the init routine, then reuse it as AppleTalk gets
  121.  *  turned on.  The use of the global var only makes sense is the application is to
  122.  *  be AppleTalk safe.  That is the user can turn AppleTalk on and off, and DMZ
  123.  *    does the right thing to protect itself
  124.  */
  125. ATalkTransitionEventUPP gAtalkTransUPP;        /* appletalk transition queue handler */
  126.  
  127. /* powerpc stuff */
  128.  
  129.  
  130. #ifdef GENERATINGCFM
  131. #ifndef __MWERKS__
  132. QDGlobals qd;                                /* quickdraw globals */
  133. #endif
  134. #endif
  135.  
  136. /*
  137.  *    The Routines for dmzMain.
  138.  */
  139.  
  140.  
  141. /*
  142.  *    Draws an outline around the particular item in the dialog.
  143.  */
  144. void DrawBoldItem(WindowPtr whichWindow, short theItem, short whichStrID)
  145. {
  146.     Rect         r;
  147.     short        kind;
  148.     Handle        h;
  149.     Str255        str;
  150.     FontInfo    info;
  151.     
  152.     GetFontInfo(&info);
  153.     GetDialogItem(whichWindow, theItem, &kind, &h, &r);
  154.     TextFace(bold);
  155.     MoveTo(r.left, r.top + info.ascent);
  156.     GetIndString(str, kStringListID, whichStrID);
  157.     DrawString(str);
  158.     TextFace(0);
  159. }
  160.  
  161. /*
  162.  *    Main dialog handling routines for user item updating.  Here we'll update the 
  163.  *    two lists using _LUpdate and also draw a border around the list rectangles 
  164.  *    themselves.  We're actually drawing across the whole length of the content
  165.  *    region and not sure around the rView.  This is because the 6.x & older 
  166.  *    List Managers erase the region where the scoll bar use to be.  Since this
  167.  *    kinda bites we have to draw something to replace that whole.
  168.  *
  169.  *    Notice that the routine has to use Pascal calling conventions.
  170.  */
  171. pascal void updateUserItems(WindowPtr whichWindow, short theItem)
  172. {
  173.     GrafPtr     savedPort;
  174.     Rect         r;
  175.     
  176.     GetPort(&savedPort);
  177.     SetPort(whichWindow);
  178.  
  179.     switch(theItem) {
  180.         case kZoneListID:
  181.             LUpdate((*(**gZonesList).port).visRgn, gZonesList);
  182.             r = (**gZonesList).rView;
  183.             MoveTo(whichWindow->portRect.left, r.top-1);
  184.             LineTo(whichWindow->portRect.right, r.top-1);
  185.             MoveTo(whichWindow->portRect.left, r.bottom);
  186.             LineTo(whichWindow->portRect.right, r.bottom);
  187.             break;
  188.         case kNameTypeListID:
  189.             LUpdate((*(**gObjectTypeList).port).visRgn, gObjectTypeList);
  190.             r = (**gObjectTypeList).rView;
  191.             MoveTo(whichWindow->portRect.left, r.top-1);
  192.             LineTo(whichWindow->portRect.right, r.top-1);
  193.             MoveTo(whichWindow->portRect.left, r.bottom);
  194.             LineTo(whichWindow->portRect.right, r.bottom);
  195.             break;
  196.         case kZoneItemID:
  197.             DrawBoldItem(whichWindow, theItem, kZoneStrID);
  198.             break;
  199.         case kObjectID:
  200.             DrawBoldItem(whichWindow, theItem, kObjectStrID);
  201.             break;
  202.         case kTypeID:
  203.             DrawBoldItem(whichWindow, theItem, kTypeStrID);
  204.             break;
  205.         case kNetID:
  206.             DrawBoldItem(whichWindow, theItem, kNetStrID);
  207.             break;
  208.         case kNodeID:
  209.             DrawBoldItem(whichWindow, theItem, kNodeStrID);
  210.             break;
  211.         case kSocketID:
  212.             DrawBoldItem(whichWindow, theItem, kSktStrID);
  213.             break;
  214.         default:
  215.             break;
  216.         }
  217.     SetPort(savedPort);
  218. }
  219.     
  220. /* 
  221.  *    Generic routine for setting up dialog user items update procedure.  Saves us a 
  222.  *    few bytes by not duplicating the routine for each item.
  223.  */
  224. void getandSetIt(short whichID)
  225. {
  226.     Rect     r;
  227.     short    kind;
  228.     Handle    h;
  229.     static UserItemUPP    gUpdateUserItemsUPP = nil;
  230.     
  231.     GetDialogItem(gMyDialog, whichID, &kind, &h, &r);
  232.     
  233.     if (gUpdateUserItemsUPP==nil)
  234.         gUpdateUserItemsUPP = NewUserItemProc(updateUserItems);
  235.     SetDialogItem(gMyDialog, whichID, userItem, (Handle) gUpdateUserItemsUPP, &r);
  236. }
  237.     
  238. /* 
  239.  *    For each userItem in the list, we'll call getandSetIt() to set up the 
  240.  *    update procedure pointer.  We'll also set up the port's font & size here.
  241.  */
  242. void setupUserItems(void)
  243. {
  244.     GrafPtr savedPort;
  245.     
  246.     GetPort(&savedPort);
  247.     SetPort(gMyDialog);
  248.     
  249.     TextFont(monaco);
  250.     TextSize(9);
  251.     
  252.     getandSetIt(kZoneListID);
  253.     getandSetIt(kNameTypeListID);
  254.     getandSetIt(kZoneItemID);
  255.     getandSetIt(kObjectID);
  256.     getandSetIt(kTypeID);
  257.     getandSetIt(kNetID);
  258.     getandSetIt(kNodeID);
  259.     getandSetIt(kSocketID);
  260.     
  261.     SetPort(savedPort);
  262. }
  263.  
  264. /* 
  265.  *    This sets the value of the lookup item control to on
  266.  */
  267. void setupLookupItem(void)
  268. {
  269.     short        kind;
  270.     Handle        h;
  271.     Rect        r;
  272.  
  273.     GetDialogItem(gMyDialog, kDoLookupID, &kind, &h, &r);
  274.     SetControlValue((ControlHandle)h, 1);
  275. }
  276.  
  277. /* 
  278.  *    This changes the current value of the gDoLookUp flag and reflects the state in the 
  279.  *    control
  280.  */
  281. void doLookupItem(void)
  282. {
  283.     short        kind;
  284.     Handle        h;
  285.     Rect        r;
  286.  
  287.     GetDialogItem(gMyDialog, kDoLookupID, &kind, &h, &r);
  288.     
  289.     gContLookUp ^= 1; /* assigns bitwise XOR (changes from on to off and visa versa) */
  290.  
  291.     SetControlValue((ControlHandle)h, (short)gContLookUp);
  292. }
  293.  
  294. /*
  295.  *     Set the default state of a large window for zooming 
  296.  */
  297. void setWindowStdState(WindowPtr theWindow)
  298. {
  299.     Rect        wRect;
  300.     Point        tlP, brP;
  301.     GrafPtr        savePort;
  302.     
  303.     GetPort(&savePort);
  304.     SetPort(theWindow);
  305.     
  306.     /* 
  307.      *    set the userState - convert coords to globals 
  308.      */
  309.     tlP.h = theWindow->portRect.left;
  310.     tlP.v = theWindow->portRect.top;
  311.     brP.h = theWindow->portRect.right;
  312.  
  313. #ifdef THINK_C
  314.     brP.v = screenBits.bounds.bottom-45;
  315. #else
  316.     brP.v = qd.screenBits.bounds.bottom-45;
  317. #endif
  318.  
  319.     LocalToGlobal(&tlP);
  320.     LocalToGlobal(&brP);
  321.     
  322.     wRect.left = tlP.h;
  323.     wRect.top = tlP.v;
  324.     wRect.right = brP.h;
  325.     wRect.bottom = brP.v;
  326.     
  327.     (**(WStateData **) (*(WindowPeek)theWindow).dataHandle).stdState = wRect;
  328.  
  329.     SetPort(savePort);
  330. }
  331.  
  332.  
  333. /*
  334.  *     Create our one and only dialog from the DLOG resource.
  335.  *     If the DLOG resource isn't there, go wash your socks.
  336.  */
  337. void setUpDialogs(void)
  338. {
  339.  
  340.     /*
  341.      *    make sure there is a 'dctb' resource present so color stuff works!
  342.      */
  343.     gMyDialog = GetNewDialog(kMainDialogID, nil, (WindowPtr) -1);
  344.     gLookupDialog = GetNewDialog(kLookupDialogID, nil, (WindowPtr) -1);
  345.  
  346.     setWindowStdState(gMyDialog);
  347.     
  348.     setupUserItems();
  349. }
  350.  
  351. /* 
  352.  *    This frames the Object, type, etc. items in the main dialog window.  This tells the 
  353.  *    user which item the list is currently sorting on. The box size is based on the
  354.  *    size of the text itself and not on the dialog item rectangle size.  On a machine which
  355.  *    supports color, we'll use RGB value form HiliteRGB for the outline box color. No need
  356.  *    for this utlity to use stodgy old black and white if it doesn' t have too.. And it 
  357.  *    also adds some uniformity to the selection idea since the lists also use HiliteRGB.
  358.  *    One thing we do not do with the selection is remove it if window is in background...
  359.  *    ...should we to be truley HIG compatible?
  360.  */
  361. void FrameItem(DialogPtr whichDialog, short whichItem)
  362. {
  363.     short        kind;
  364.     Handle        h;
  365.     Rect        r;
  366.     PenState    ps;
  367.     RGBColor    rgb, curRGB;
  368.     unsigned char    str[10];
  369.     FontInfo    info;
  370.     short        strListID;
  371.     GrafPtr        savePort;
  372.     
  373.     GetPort(&savePort);
  374.     SetPort(whichDialog);
  375.     
  376.     TextFace(bold);
  377.  
  378.     /* 
  379.      *    unframe old item 
  380.      */
  381.     GetDialogItem(whichDialog, gSortItem, &kind, &h, &r);
  382.     
  383.     switch (gSortItem) {
  384.         case kObjectID:
  385.             strListID = kObjectStrID;
  386.             break;
  387.         case kTypeID:
  388.             strListID = kTypeStrID;
  389.             break;
  390.         case kNetID:
  391.             strListID = kNetStrID;
  392.             break;
  393.         case kNodeID:
  394.             strListID = kNodeStrID;
  395.             break;
  396.         case kSocketID:
  397.             strListID = kSktStrID;
  398.             break;
  399.         }
  400.         
  401.     GetIndString(str, kStringListID, strListID);
  402.     GetPenState(&ps);
  403.  
  404.     PenPat(&qd.white);
  405.     GetFontInfo(&info);
  406.     r.right = r.left + StringWidth(str) + 2;
  407.     r.left -= 2;
  408.     r.bottom = r.top;
  409.     r.bottom += info.ascent + info.descent + 2;    
  410.     r.top -= 1;
  411.     FrameRect(&r);
  412.     SetPenState(&ps);
  413.  
  414.     /* 
  415.      *    If Color QD is present, we will change the foreground color to HiliteRGB
  416.      *    so that our "selection" frame will match our list's hilites.
  417.      */
  418.     if(GMAC.hasColorQD) {
  419.         BlockMove((Ptr) HiliteRGB,(Ptr)  &rgb, sizeof(RGBColor));
  420.         GetForeColor(&curRGB);
  421.         RGBForeColor(&rgb);
  422.     }
  423.  
  424.     /* 
  425.      *    frame new item 
  426.      */
  427.     switch (whichItem) {
  428.         case kObjectID:
  429.             strListID = kObjectStrID;
  430.             break;
  431.         case kTypeID:
  432.             strListID = kTypeStrID;
  433.             break;
  434.         case kNetID:
  435.             strListID = kNetStrID;
  436.             break;
  437.         case kNodeID:
  438.             strListID = kNodeStrID;
  439.             break;
  440.         case kSocketID:
  441.             strListID = kSktStrID;
  442.             break;
  443.         }
  444.         
  445.     GetDialogItem(whichDialog, whichItem, &kind, &h, &r);
  446.     GetIndString(str, kStringListID, strListID);
  447.  
  448.     GetFontInfo(&info);
  449.     r.right = r.left + StringWidth(str) + 2;
  450.     r.left -= 2;
  451.     r.bottom = r.top;
  452.     r.bottom += info.ascent + info.descent + 2;    
  453.     r.top -= 1;
  454.     FrameRect(&r);
  455.     
  456.     TextFace(0);
  457.  
  458.     /* 
  459.      *    Reset foreground color.
  460.      */
  461.     if(GMAC.hasColorQD)
  462.         RGBForeColor(&curRGB);
  463.     
  464.     gSortItem = whichItem;
  465.  
  466.     SetPort(savePort);
  467. }
  468.  
  469. /* 
  470.  *    This is the routine called by _DialogSelect.  It handles all userItem events
  471.  *    except updating.
  472.  */
  473. void doModeless(DialogPtr whichDialog, short whichItem)
  474. {        
  475.     if(whichDialog == gMyDialog) {
  476.         switch(whichItem) {
  477.             case kZoneListID: /* 1 */
  478.                 doZonesListStuff();
  479.                 break;
  480.             case kNameTypeListID: /* 2 */
  481.                  doObjectTypeListStuff();
  482.                  break;
  483.             case kObjectID:
  484.                 gSortMode = sortOnObject;
  485.                 FrameItem(whichDialog, whichItem);
  486.                 getTypesNamesInZone(gNameGlob);
  487.                 break;
  488.             case kTypeID:
  489.                 gSortMode = sortOnType;
  490.                 FrameItem(whichDialog, whichItem);
  491.                 getTypesNamesInZone(gNameGlob);
  492.                 break;
  493.             case kNetID:
  494.                 gSortMode = sortOnNet;
  495.                 FrameItem(whichDialog, whichItem);
  496.                 getTypesNamesInZone(gNameGlob);
  497.                 break;
  498.             case kNodeID:
  499.                 gSortMode = sortOnNode;
  500.                 FrameItem(whichDialog, whichItem);
  501.                 getTypesNamesInZone(gNameGlob);
  502.                 break;
  503.             case kSocketID:    
  504.                 gSortMode = sortOnSocket;
  505.                 FrameItem(whichDialog, whichItem);
  506.                 getTypesNamesInZone(gNameGlob);
  507.                 break;
  508.             default:
  509.                 break;
  510.             }
  511.     }
  512. }
  513.         
  514. /*    
  515.  *    doIdle()  Called repeatedly in main event loop for cursor tasks
  516.  *    and NBPLookups.
  517.  */
  518. void doIdle(void)     
  519. {
  520.     SpinTheCursor();
  521.     if(gUpdateListFlag == true) {
  522.         processListUpdate();
  523.     }
  524. }
  525.  
  526. /* 
  527.  *    draws the grow box 
  528.  */ 
  529. void DrawGrowBox(WindowPtr theWindow)
  530. {
  531.     Rect        r, windowRect;
  532.     GrafPtr        tempPort;
  533.     
  534.     /*
  535.      *    copy theWindow->portRect into a local rect for efficency.  
  536.      *    no need to dereference theWindow all the time.
  537.      */
  538.     GetPort(&tempPort);
  539.     SetPort(theWindow);
  540.     
  541.     windowRect = theWindow->portRect;
  542.     
  543.     if(((WindowPeek)theWindow)->hilited) {
  544.         MoveTo(windowRect.right-12, windowRect.bottom-12);
  545.         LineTo(windowRect.right-6, windowRect.bottom-12);
  546.         LineTo(windowRect.right-6, windowRect.bottom-6);
  547.         LineTo(windowRect.right-12, windowRect.bottom-6);
  548.         LineTo(windowRect.right-12, windowRect.bottom-12);
  549.     
  550.         MoveTo(windowRect.right-5, windowRect.bottom-10);
  551.         LineTo(windowRect.right-2, windowRect.bottom-10);
  552.         LineTo(windowRect.right-2, windowRect.bottom-2);
  553.         LineTo(windowRect.right-10, windowRect.bottom-2);
  554.         LineTo(windowRect.right-10, windowRect.bottom-5);
  555.         }
  556.     else {
  557.         SetRect(&r, windowRect.right-17, windowRect.bottom-15,
  558.             windowRect.right, windowRect.bottom);
  559.         EraseRect(&r);
  560.         }
  561.  
  562.     MoveTo(windowRect.right-15, windowRect.bottom);
  563.     LineTo(windowRect.right-15, windowRect.bottom-15);
  564.     MoveTo(windowRect.right-15, windowRect.bottom-15);
  565.     LineTo(windowRect.right, windowRect.bottom-15);
  566.  
  567.     SetPort(tempPort);
  568. }
  569.  
  570. /* 
  571.  *    updates the gSortItem rectangle 
  572.  */
  573. void doUpdate(WindowPtr theWindow)
  574. {
  575.     RGBColor    rgb, curRGB;
  576.     
  577.     if(theWindow == gMyDialog) 
  578.     {
  579.         if(GMAC.hasColorQD) 
  580.         {
  581.             BlockMove((Ptr) HiliteRGB, (Ptr) &rgb, sizeof(RGBColor));
  582.             GetForeColor(&curRGB);
  583.             RGBForeColor(&rgb);
  584.         }
  585.     
  586.         FrameItem(gMyDialog, gSortItem);
  587.         if(GMAC.hasColorQD)
  588.             RGBForeColor(&curRGB);
  589.         DrawGrowBox(theWindow);
  590.     }
  591. }
  592.  
  593.  
  594. /*    
  595.  *    ShowMainWindowAndSizeIt() opens our main window to the size of our main screen
  596.  *    and displays it.
  597.  */
  598. void ShowMainWindowAndSizeIt(void)
  599. {
  600.     extern void DoZoomWindow(WindowPtr whichWindow, short partCode);
  601.     
  602.     /*
  603.      *    show it…
  604.      */
  605.     ShowWindow(gMyDialog);
  606.     
  607.     /*
  608.      *    and resize it.
  609.      */
  610.     /* DoZoomWindow(gMyDialog, inZoomOut); */
  611. }
  612.  
  613.  
  614. /*    
  615.  *    doInitializing() Called at application boot to allocate master pointers,
  616.  *    check SysEnvirons() for Mac type, check for WaitNextEvent implementation.
  617.  *    and call all other initializing routines.
  618.  */
  619. void doInitializing(void)
  620. {
  621.     extern        void setupMenus();
  622.     OSErr        ignoreError, err;
  623.     short        count;
  624.     
  625.     /*
  626.      * Initialization traps
  627.      */
  628.     MaxApplZone();
  629.  
  630.     MoreMasters();
  631.     MoreMasters();
  632.     MoreMasters();
  633.     MoreMasters();
  634.     
  635.     /* 
  636.      *    ignore the error returned from SysEnvirons; even if an error occurred,
  637.      *    the SysEnvirons glue will fill in the SysEnvRec 
  638.      */
  639.     ignoreError = SysEnvirons(sysEnvironsVersion, &GMAC);
  640.     if ( GMAC.machineType < 0 )                 /*old machines have...*/ 
  641.         gHasWaitNextEvent = false;             /*no separate trap table; no WaitNextEvent */
  642.     else
  643.         gHasWaitNextEvent = TrapAvailable(_WaitNextEvent);
  644.  
  645.     gInBackground = false;
  646.  
  647. #ifdef THINK_C
  648.     InitGraf(&thePort);
  649. #else
  650.     InitGraf(&qd.thePort);
  651. #endif
  652.     
  653.     InitFonts();
  654.     FlushEvents(everyEvent, 0);
  655.     InitWindows();
  656.     InitMenus();
  657.     InitDialogs(0L);    
  658.  
  659.     /*    
  660.      *    This next bit of code is necessary to allow the default button of our
  661.      *    alert be outlined.
  662.      *    Changed to call _EventAvail so that we don't lose some important
  663.      *    events. 
  664.      */     
  665.     for (count = 1; count <= 3; count++) {
  666.         EventAvail(everyEvent, &gMyEvent);
  667.     }
  668.  
  669.     /* 
  670.      *    make 'em wait 
  671.      */
  672.         // set up for the alternative spin cursor
  673.     InitAnimatedCursors(kDMZ_ACUR_ID);
  674.  
  675.     /* 
  676.      *    setupmenus 
  677.      */
  678.     setupMenus();            
  679.  
  680.     /*
  681.      * setup the dialog.
  682.      */
  683.     setUpDialogs();
  684.     SetPort(gMyDialog);
  685.     
  686.     /*
  687.      * is VM on
  688.      * this must be determined before calling InitEchoBuffers which gets called from
  689.      * InitAppleTalkVars
  690.      */
  691.     if (IsVMOn())
  692.         gATalkFlags |= (1 << kVMActive);
  693.     
  694.     /*
  695.      * setup the list stuff.
  696.      */
  697.     OpenZonesList();
  698.     OpenObjectTypeList();
  699.  
  700.     /*
  701.      * initialize assorted and sundry variables
  702.      */
  703.     gDoneFlag = false;
  704.     gNameGlob[0] = 0;
  705.     gUpdateListFlag = false;
  706.     gLookupFinished = true;
  707.     gSortMode = sortOnObject;
  708.  
  709.         // allocate memory for our globals
  710.     gATQEntry.globs = NewHandleClear(sizeof(myATQEntry));
  711.     if (gATQEntry.globs == nil) 
  712.     {
  713.         BigBadError("\pError allocating memory - Aborting program");
  714.     }
  715.  
  716.     /*
  717.      * setup the appletalk stuff.
  718.      */
  719.     InitAppleTalkVars();
  720.     
  721.     /*
  722.      * install our transition queue handler
  723.      */
  724.     if (LAPMgrExists()) 
  725.     {
  726.  
  727.         gATQEntry.myA5 = (long)LMGetCurrentA5(); /* get the Current A5 */
  728.             
  729.         gAtalkTransUPP = NewATalkTransitionEventProc(ATalkTransQueue);
  730.         gATQEntry.CallAddr = gAtalkTransUPP;
  731.         err = LAPAddATQ((ATQEntry*)&gATQEntry);
  732.         if (err == noErr) 
  733.         {
  734.             gATalkFlags |= (1 << kATQInstalled);        /* indicate that the trans queue was installed */
  735.         }
  736.         else
  737.             BigBadError("\pError setting up AppleTalk - Aborting program");
  738.     }
  739.     else
  740.     {
  741.         BigBadError("\pThis program requires AppleTalk version 53 or greater");
  742.     }
  743.  
  744.     /*
  745.      * open the main window & size it to the main screen.
  746.      */
  747.     ShowMainWindowAndSizeIt();
  748.         
  749.     InitCursor();
  750. }
  751.     
  752. /*
  753.  *    uses predefined value to calculate 'grid height' of list.
  754.  */
  755. short resizeRectToListCellSize(short height)
  756. {
  757.     short    temp;
  758.  
  759.     height -= 113;
  760.     temp = height % 11;
  761.     height += (113 - temp);
  762.  
  763.     return height;
  764. }
  765.  
  766. void resizeWindow(WindowPtr whichWindow, short height)
  767. {
  768.     short        kind;
  769.     Handle        h;
  770.     Rect            r;
  771.     RgnHandle    savedClipRgn, theListMgrSucksRgn;
  772.  
  773.     /*
  774.      *    this 'grids' the bottom of the window to the right height to fit the list cell size
  775.      */
  776.     SizeWindow(whichWindow, whichWindow->portRect.right-whichWindow->portRect.left, height, true);
  777.  
  778.     GetDialogItem(gMyDialog, kNameTypeListID, &kind, &h, &r);
  779.     
  780.     savedClipRgn = NewRgn();
  781.     theListMgrSucksRgn = NewRgn();
  782.     GetClip(savedClipRgn);
  783.     SetClip(theListMgrSucksRgn);
  784.     
  785.     r.bottom = whichWindow->portRect.bottom;
  786.     SetDialogItem(gMyDialog, kNameTypeListID, kind, h, &r);
  787.     
  788.     LSize((**gObjectTypeList).rView.right-(**gObjectTypeList).rView.left, (whichWindow->portRect.bottom)-(**gObjectTypeList).rView.top, gObjectTypeList);
  789.  
  790.     SizeControl((**gObjectTypeList).vScroll, (**(**gObjectTypeList).vScroll).contrlRect.right - 
  791.         (**(**gObjectTypeList).vScroll).contrlRect.left, (**(**gObjectTypeList).vScroll).contrlRect.bottom - 
  792.         (**(**gObjectTypeList).vScroll).contrlRect.top - 15);
  793.  
  794.     SetClip(savedClipRgn);
  795.     DisposeRgn(savedClipRgn);
  796.     DisposeRgn(theListMgrSucksRgn);
  797.  
  798.     /*
  799.      *    Erase grow box icon
  800.      */
  801.     SetRect(&r, whichWindow->portRect.right-14, whichWindow->portRect.bottom-15, 
  802.         whichWindow->portRect.right, whichWindow->portRect.bottom);
  803.     EraseRect(&r);
  804. }
  805.  
  806. /*    
  807.  *    Check to see if a window belongs to the application. If the window pointer
  808.  *    passed was NIL, then it could not be an application window. WindowKinds
  809.  *    that are negative belong to the system and windowKinds less than userKind
  810.  *    are reserved by Apple except for windowKinds equal to dialogKind, which
  811.  *    mean it is a dialog.
  812.  *    1.02 - In order to reduce the chance of accidentally treating some window
  813.  *    as an AppWindow that shouldn't be, we'll only return true if the windowkind
  814.  *    is userKind. If you add different kinds of windows to Sample you'll need
  815.  *    to change how this all works. 
  816.  */
  817.  
  818. Boolean IsAppWindow(WindowPtr window)
  819. {
  820.     short        windowKind;
  821.  
  822.     if ( window == nil )
  823.         return false;
  824.     else {    /* application windows have windowKinds = userKind (8) */
  825.         windowKind = ((WindowPeek) window)->windowKind;
  826.         return (windowKind == userKind);
  827.     }
  828. } /*IsAppWindow*/
  829.  
  830.  
  831. /* Check to see if a window belongs to a desk accessory. */
  832.  
  833. Boolean IsDAWindow(WindowPtr window)
  834. {
  835.     if ( window == nil )
  836.         return false;
  837.     else    /* DA windows have negative windowKinds */
  838.         return ((WindowPeek) window)->windowKind < 0;
  839. } /*IsDAWindow*/
  840.  
  841.  
  842. /* Close a window. This handles desk accessory and application windows. */
  843.  
  844. /*    
  845.  *    1.01 - At this point, if there was a document associated with a
  846.  *    window, you could do any document saving processing if it is 'dirty'.
  847.  *    DoCloseWindow would return true if the window actually closed, i.e.,
  848.  *    the user didn’t cancel from a save dialog. This result is handy when
  849.  *    the user quits an application, but then cancels the save of a document
  850.  *    associated with a window. 
  851.  */
  852.  
  853. Boolean DoCloseWindow(WindowPtr window)
  854. {
  855.     if ( IsDAWindow(window) )
  856.         CloseDeskAcc(((WindowPeek) window)->windowKind);
  857.     else if ( window == gLookupDialog ) {
  858.         HideWindow(window);
  859.     }
  860.     return true;
  861. } /*DoCloseWindow*/
  862.  
  863.  
  864. /*
  865.  *    The USER, let's call him "Bob", has clicked in the zoom box so now he, "Bob", probably expects
  866.  *    us to do something about it.
  867.  */
  868.  
  869. void DoZoomWindow(WindowPtr whichWindow, short partCode)
  870. {
  871.     WindowPeek        wp;
  872.     WStateData        **wStateH;
  873.     Rect            globalPortRect, theSect, zoomRect;
  874.     GDHandle        nthDevice, dominantGDevice;
  875.     long            sectArea, greatestArea;
  876.     short            bias;
  877.     Boolean            sectFlag;
  878.     short            windowHeight, windowWidth;
  879.     
  880.     wp = (WindowPeek) whichWindow;
  881.  
  882.     SetPort(whichWindow);
  883.     EraseRect(&whichWindow->portRect);
  884.     
  885.     wStateH = (WStateData **)wp->dataHandle;
  886.  
  887.     if(partCode == inZoomOut) {
  888.         if(GMAC.hasColorQD) {
  889.             /* 
  890.                *    Get the width of our window for later use. 
  891.                */
  892.             windowWidth = whichWindow->portRect.right - whichWindow->portRect.left;
  893.  
  894.             /* 
  895.                *    window's portRect must be converted to global coordinates... a pain in C...
  896.                */
  897.             globalPortRect = (**(*(WindowPeek)whichWindow).strucRgn).rgnBBox; /*whichWindow->portRect;*/
  898.             
  899.             /*
  900.             pt.h = globalPortRect.left;
  901.             pt.v = globalPortRect.top;
  902.             LocalToGlobal(&pt);
  903.             globalPortRect.left = pt.h;
  904.             globalPortRect.top = pt.v;
  905.     
  906.             pt.h = globalPortRect.right;
  907.             pt.v = globalPortRect.bottom;
  908.             LocalToGlobal(&pt);
  909.             globalPortRect.right = pt.h;
  910.             globalPortRect.bottom = pt.v;
  911.             */
  912.  
  913.             /*
  914.              *    Now let's calculate the height of the window's title bar 
  915.              */
  916.             bias = (**(*(WindowPeek)whichWindow).contRgn).rgnBBox.top -
  917.                 (**(*(WindowPeek)whichWindow).strucRgn).rgnBBox.top - 1; 
  918.             
  919.             nthDevice = GetDeviceList();
  920.  
  921.             /*
  922.              *    This loop checks the window against all the gdRects in the   
  923.              *    gDevice list and remembers which gdRect contains the largest 
  924.              *    portion of the window being zoomed. 
  925.              */
  926.             greatestArea = 0;
  927.             while(nthDevice != 0L) {
  928.                 sectFlag = SectRect(&globalPortRect, &(**nthDevice).gdRect, &theSect);
  929.                 sectArea = (long)(theSect.right - theSect.left) * (theSect.bottom - theSect.top);
  930.                 if(sectArea > greatestArea) {
  931.                     greatestArea = sectArea;
  932.                     dominantGDevice = nthDevice;
  933.                     }
  934.                 nthDevice = GetNextDevice(nthDevice);
  935.                 } 
  936.             
  937.             /*
  938.              *    We must create a zoom rectangle manually in this case. 
  939.              *    account for menu bar height as well, if on main device 
  940.              */
  941.             if (dominantGDevice == GetMainDevice()) 
  942.                 bias = bias + GetMBarHeight();
  943.               
  944.             /*
  945.              *    Now let's set our newly discovered 'zoom' rectangle. 3 is the recommend inset
  946.              *    value from the device's boundries.
  947.              */
  948.             SetRect(&zoomRect,(**dominantGDevice).gdRect.left+3,(**dominantGDevice).gdRect.top+bias+3,
  949.                 (**dominantGDevice).gdRect.right-3,(**dominantGDevice).gdRect.bottom-3);
  950.               
  951.             /*
  952.              *    Set up the WStateData record for this window. 
  953.              */
  954.             (**wStateH).stdState = zoomRect;
  955.             windowHeight = zoomRect.bottom-zoomRect.top;
  956.  
  957.             /*
  958.              *    Resize the bottom coordinate based on the size of a cell for neatness. 
  959.              */
  960.             (**wStateH).stdState.bottom = zoomRect.top + resizeRectToListCellSize(windowHeight);
  961.             
  962.             /*
  963.              *    We have a fixed width for our window.  Reset it now. 
  964.              */
  965.             (**wStateH).stdState.right = (**wStateH).stdState.left + windowWidth;
  966.             }
  967.         else {
  968.             /*
  969.              *    We (probably) only have one device so this is all we need to do. 
  970.              */
  971. #ifdef THINK_C
  972.             windowHeight = screenBits.bounds.bottom-7-(**wStateH).stdState.top;
  973. #else
  974.             windowHeight = qd.screenBits.bounds.bottom-7-(**wStateH).stdState.top;
  975. #endif
  976.             (**wStateH).stdState.bottom = (**wStateH).stdState.top + resizeRectToListCellSize(windowHeight);
  977.             }
  978.         }
  979.         
  980.     ZoomWindow(whichWindow, partCode, true);
  981.     resizeWindow(whichWindow, (short) (whichWindow->portRect.bottom-whichWindow->portRect.top));
  982. }
  983.  
  984. void DoGrowWindow(WindowPtr whichWindow, EventRecord    *evt)
  985. {
  986.     Rect        limitRect;
  987.     long        newSize;
  988.     GrafPtr        savePort;
  989.     short        height;
  990.     
  991.     GetPort(&savePort);
  992.     
  993. #ifdef THINK_C
  994.     limitRect = screenBits.bounds;
  995. #else
  996.     limitRect = qd.screenBits.bounds;
  997. #endif
  998.  
  999.     SetPort(whichWindow);
  1000.  
  1001.     limitRect.right = whichWindow->portRect.right + 1;
  1002.     limitRect.left = whichWindow->portRect.right + 1;
  1003.     limitRect.top = whichWindow->portRect.top + 203;
  1004.     
  1005.     newSize = GrowWindow(whichWindow, evt->where, &limitRect);
  1006.  
  1007.     if(newSize != 0L) {
  1008.         /* 
  1009.          *    set to our dialog, erase the content region and re-size the window
  1010.          */
  1011.         /* SizeWindow(whichWindow, LoWord(newSize), height, true);*/
  1012.         height = HiWord(newSize);
  1013.         height = resizeRectToListCellSize(height);
  1014.         resizeWindow(whichWindow, height);
  1015.         }
  1016.  
  1017.     SetPort(savePort);
  1018. }
  1019.  
  1020. void main(void)
  1021. {
  1022.     WindowPtr            whichWindow;
  1023.     DialogPtr            whichDialog;
  1024.     short                 whichItem;
  1025.     Boolean                processIt;
  1026.     short                partCode;
  1027.     EventRecord            myEvent;
  1028.         
  1029.     doInitializing();
  1030.     
  1031.     for ( ;; ) {
  1032.         if (gDoneFlag) 
  1033.             break;        /* from main event loop */
  1034.             
  1035.         if ( gHasWaitNextEvent ) 
  1036.             /* 
  1037.              *    no sleeping for us... 
  1038.              */
  1039.             processIt = WaitNextEvent(everyEvent, &myEvent, 0L, 0L);
  1040.         else {
  1041.             SystemTask();
  1042.             processIt = GetNextEvent(everyEvent, &myEvent);
  1043.             }
  1044.  
  1045.         /* 
  1046.          *    this checks to make sure we don't pass any cmd key events to the 
  1047.          *    modeless dialog.  This must be called even if the event traps
  1048.          *    return false for text edit idling.
  1049.          */
  1050.         /*
  1051.         if(!((myEvent.what==keyDown)&&(gMyEvent.modifiers & cmdKey))) {
  1052.             if (!((gMyEvent.what==keyDown)&&((char)(gMyEvent.message & charCodeMask))>'9')
  1053.             &&!((gMyEvent.what==keyDown)&&((char)(gMyEvent.message & charCodeMask))<(char)8)) {
  1054.                 if(IsDialogEvent(&gMyEvent)) {
  1055.                     if(DialogSelect(&gMyEvent, &whichDialog, &whichItem))
  1056.                         doModeless(whichDialog, whichItem);
  1057.                 }
  1058.             }
  1059.         }
  1060.         */
  1061.         
  1062.         if(!(myEvent.modifiers & cmdKey)) {
  1063.             if(IsDialogEvent(&myEvent)) {
  1064.                 if(DialogSelect(&myEvent, &whichDialog, &whichItem))
  1065.                     doModeless(whichDialog, whichItem);
  1066.             }
  1067.         }
  1068.         gMyEvent = myEvent;
  1069.         
  1070.         /*
  1071.         if(IsDialogEvent(&myEvent)) {
  1072.             if(DialogSelect(&myEvent, &whichDialog, &whichItem)) {
  1073.                 if(whichDialog == gMyDialog)
  1074.                     doModeless(whichDialog, whichItem);    
  1075.                 }
  1076.         }
  1077.         */
  1078.         
  1079.          {    
  1080.             switch (myEvent.what) 
  1081.             {    
  1082.                 case nullEvent:
  1083.                     doIdle();
  1084.                     break;
  1085.                                 
  1086.                 case mouseDown:
  1087.                     partCode = FindWindow(myEvent.where, &whichWindow);
  1088.                     switch (partCode) 
  1089.                         {
  1090.                         case inSysWindow:
  1091.                             SystemClick(&myEvent, whichWindow);
  1092.                             break;
  1093.     
  1094.                         case inMenuBar:
  1095.                             doCommand(MenuSelect(myEvent.where));
  1096.                             break;
  1097.     
  1098.                         case inDrag:
  1099.                             #ifdef THINK_C
  1100.                                 DragWindow(whichWindow, myEvent.where, &screenBits.bounds);
  1101.                             #else
  1102.                                 DragWindow(whichWindow, myEvent.where, &qd.screenBits.bounds);
  1103.                             #endif
  1104.                             break;
  1105.     
  1106.                         case inGoAway:
  1107.                             if (TrackGoAway(whichWindow, myEvent.where))
  1108.                                 DoCloseWindow(whichWindow);             /* we don’t care if the user cancelled */
  1109.                             break;
  1110.     
  1111.                         case inGrow:
  1112.                             DoGrowWindow(whichWindow, &myEvent);
  1113.                             break;
  1114.     
  1115.                         case inContent:
  1116.                             if(whichWindow != FrontWindow())
  1117.                                 SelectWindow(whichWindow);
  1118.                             break;
  1119.     
  1120.                         case inZoomIn:
  1121.                         case inZoomOut:
  1122.                             if(whichWindow == FrontWindow()) {
  1123.                                 if(TrackBox(whichWindow, myEvent.where, partCode)) 
  1124.                                     DoZoomWindow(whichWindow, partCode);
  1125.                                 }
  1126.                             break;
  1127.     
  1128.                         default:
  1129.                             break;
  1130.                         }
  1131.                     break;
  1132.     
  1133.                 case keyDown:
  1134.                 case autoKey:
  1135.                     if (gMyDialog == FrontWindow()) {
  1136.                         if (myEvent.modifiers & cmdKey) 
  1137.                             doCommand(MenuKey(myEvent.message & charCodeMask));
  1138.                         else if ((myEvent.message & charCodeMask) == kEnterKey
  1139.                             || (myEvent.message & charCodeMask) == kReturnKey)
  1140.                             doObjectDoubleClick();
  1141.                         }
  1142.                     else if (gLookupDialog == FrontWindow())
  1143.                         if (myEvent.modifiers & cmdKey) 
  1144.                             doCommand(MenuKey(myEvent.message & charCodeMask));
  1145.                     break;
  1146.     
  1147.                 case activateEvt:
  1148.                     if ((WindowPtr) myEvent.message == gMyDialog || (WindowPtr) myEvent.message == gLookupDialog) {
  1149.                         if (myEvent.modifiers & activeFlag) {
  1150.                             if ((WindowPtr) myEvent.message == gMyDialog)
  1151.                                 doActivate(gMyDialog);                        
  1152.                             DisableItem(GetMenuHandle(editID), 0);
  1153.                         } 
  1154.                         else {
  1155.                             if ((WindowPtr) myEvent.message == gMyDialog)
  1156.                                 doDeactivate(gMyDialog);                        
  1157.                             if(FrontWindow() != gMyDialog && FrontWindow() != gLookupDialog)
  1158.                                 EnableItem(GetMenuHandle(editID), 0);
  1159.                         }
  1160.                     }
  1161.                     DrawMenuBar();
  1162.                     break;
  1163.     
  1164.                 case updateEvt:
  1165.                     /* 
  1166.                      *    all our updating is handled by the Dialog Mananger
  1167.                      *     and our userItem update routines.
  1168.                      */
  1169.                      doUpdate((WindowPtr) myEvent.message);
  1170.                      break;
  1171.     
  1172.                 case osEvt:
  1173.                     switch (myEvent.message >> 24) {     /* high byte of message */
  1174.                         case mouseMovedMessage:
  1175.                             doIdle();    /* mouse moved is also an idle event */
  1176.                             break;
  1177.                         case suspendResumeMessage:
  1178.                             if ( myEvent.message & resumeMask ) {
  1179.                                 /* 
  1180.                                  *    resume event received  
  1181.                                  *  check first whether an ATalk Queue Event has occured
  1182.                                  */
  1183.                                 if (((dmzEntryPtr) *(gATQEntry.globs))->atalkStatusChanged) 
  1184.                                 {
  1185.                                     ((dmzEntryPtr) *(gATQEntry.globs))->atalkStatusChanged = false;   /* clears the changed bit */
  1186.                                     if (((dmzEntryPtr) *(gATQEntry.globs))->atalkActive) 
  1187.                                     {
  1188.                                         InitAppleTalkVars();
  1189.                                         invalidateItem(1);
  1190.                                     }
  1191.                                     else     // AppleTalk has become inactive
  1192.                                     {
  1193.                                         ClearZoneCells();
  1194.                                         ClearObjectTypesList();
  1195.                                         tellUserNoZones();
  1196.                                     }
  1197.                                 }
  1198.                                 else
  1199.                                     enableSetSelfSend();
  1200.                                 doActivate(gMyDialog);
  1201.                                 gInBackground = false;
  1202.                             } else {
  1203.                                 /* 
  1204.                                  *    suspend event received
  1205.                                  */
  1206.                                 restoreSetSelfSend();
  1207.                                 doDeactivate(gMyDialog);
  1208.                                 gInBackground = true;
  1209.                                 }
  1210.                             DrawMenuBar();
  1211.                             break;
  1212.                         }
  1213.                     break;
  1214.                 }/*endsw myEvent.what*/
  1215.             }
  1216.         }
  1217.  
  1218.     doCleanUpAndTerminate();
  1219. }
  1220.  
  1221. /*
  1222.  *     Handle any activate routines here.  In our case this mean activating the lists and redrawing
  1223.  *    our grow box.
  1224.  */
  1225. void doActivate(WindowPtr theWindow)
  1226. {
  1227.     /* 
  1228.      *    Hilites scroll bars and updates scrollbar control max fields with _LActivate(true, ...).
  1229.      */
  1230.     LActivate(true, gZonesList);
  1231.     LActivate(true, gObjectTypeList);
  1232.  
  1233.     /*     
  1234.      *    this is like really dumb but necessary for ListManager
  1235.      *    skankiness.  It forces the lists's scroll bar's to
  1236.      *    recalculate & update which is not handled by _LActivate.
  1237.  
  1238.     LUpdate((*(**gZonesList).port).visRgn, gZonesList);
  1239.     LUpdate((*(**gObjectTypeList).port).visRgn, gObjectTypeList);
  1240.     */
  1241.  
  1242.     DrawGrowBox(theWindow);
  1243. }
  1244.     
  1245. /*
  1246.  * 
  1247.  */
  1248. void doDeactivate(WindowPtr    theWindow)
  1249. {
  1250.     /* 
  1251.      *    instead of only calling _LActivate(false, ...), we're going to unhilite 
  1252.      *    the two scroll bars too.  _LActivate(false, ...) actually hides the WHOLE 
  1253.      *    scroll bar control, outline and all, which isn't really to Human Interface 
  1254.      *    Guidelines or Pete's Mom's Prairie Home Programming Rules.  Besides it 
  1255.      *    looks really silly.
  1256.      *
  1257.      *  If you want to use the LActivate instead substitute the following lines
  1258.      *    for the HilitControl and the LActivate flag lines.
  1259.      *    2/17/90 pvh - forget it.  just use the LActivate call instead.  toolbox wins.
  1260.      */
  1261.     
  1262.     LActivate(false, gZonesList);
  1263.     LActivate(false, gObjectTypeList);
  1264.     
  1265.     /*
  1266.     (**gZonesList).lActive = false;
  1267.     (**gObjectTypeList).lActive = false;
  1268.     HiliteControl((**gZonesList).vScroll, 255);
  1269.     HiliteControl((**gObjectTypeList).vScroll, 255);
  1270.     ShowControl((**gZonesList).vScroll);
  1271.     ShowControl((**gObjectTypeList).vScroll);
  1272.     */
  1273.  
  1274.     DrawGrowBox(theWindow);
  1275. }
  1276.     
  1277. /*
  1278.  * Cleanup here.  Calls all clean up routines.
  1279.  */
  1280. void doCleanUpAndTerminate(void)
  1281. {
  1282.     closeUpOurAppleTalk();
  1283.     HideWindow(gMyDialog);
  1284.     DisposOfMyLists();
  1285.     DisposeDialog(gMyDialog);
  1286.     
  1287.     ExitToShell();
  1288. }
  1289.     
  1290. /*
  1291.  * Set up the Apple, File, and Edit menus using the MBAR resource.
  1292.  * If the MENU resources are missing, we die and find something better to do.
  1293.  */
  1294. void setupMenus(void)
  1295. {
  1296.     Handle        myMenuBar;
  1297.     
  1298.     myMenuBar = GetNewMBar(128);
  1299.     SetMenuBar(myMenuBar);
  1300.     DisposeHandle(myMenuBar);
  1301.     AppendResMenu(GetMenuHandle(appleID), 'DRVR');
  1302.     
  1303.     DrawMenuBar();
  1304. }
  1305.  
  1306. /*
  1307.  * The user has tried to cut, copy or paste into the lookup dialog.
  1308.  * We'll try to handle that here.
  1309.  */
  1310. void handleLookupDialogEdit(void)
  1311. {
  1312. }
  1313.  
  1314.     
  1315. /*
  1316.  * Process mouse clicks in menu bar
  1317.  */
  1318. void doCommand(mResult)
  1319.     long    mResult;
  1320.     {
  1321.     int                 theMenu, theItem;
  1322.     Str255                daName;
  1323.     GrafPtr             savePort;
  1324.     extern void            showAboutMeDialog();
  1325.     extern Boolean        gDoneFlag;
  1326.     short                ignore;
  1327.         
  1328.     theItem = LoWord(mResult);
  1329.     theMenu = HiWord(mResult);        /* This is the resource ID */
  1330.  
  1331.     switch (theMenu) {
  1332.         case appleID:
  1333.             if (theItem == aboutMeCommand) 
  1334.                 showAboutMeDialog();
  1335.             else {
  1336.                 GetMenuItemText(GetMenuHandle(appleID), theItem, daName);
  1337.                 GetPort(&savePort);
  1338.                 ignore = OpenDeskAcc(daName);
  1339.                 SetPort(savePort);
  1340.                 }
  1341.             break;
  1342.  
  1343.         case fileID:
  1344.             switch (theItem) {
  1345.                 case lookupCommand:
  1346.                     ShowWindow(gLookupDialog);        /* show lookup prefs window */
  1347.                     SelectWindow(gLookupDialog);
  1348.                     break;
  1349.                 case quitCommand:
  1350.                     gDoneFlag = true;                /* Request exit */
  1351.                     break;
  1352.                 default:
  1353.                     break;
  1354.                 }
  1355.             break;
  1356.  
  1357.         case editID:
  1358.             /*
  1359.              * If this is for a 'standard' edit item,
  1360.              * run it through SystemEdit first.
  1361.              * SystemEdit will return false if it's not a system window.
  1362.              */
  1363.             if ((theItem <= clearCommand) && SystemEdit(theItem-1)) {
  1364.                 break;
  1365.             }
  1366.             
  1367.             /*
  1368.              * Otherwise, it's my window.
  1369.              * and we don't need the Edit menu so boogie...
  1370.              */
  1371.             if(FrontWindow() == gLookupDialog) {
  1372.                 SysBeep(1);
  1373.             }
  1374.             break;        
  1375.         default:
  1376.             break;
  1377.  
  1378.         } /*endsw theMenu*/
  1379.  
  1380.     HiliteMenu(0);
  1381. } /* doCommand */
  1382.  
  1383.  
  1384.  
  1385. /* 
  1386.  *    handles "OK" button outlining for our About...& Echo dialogs.
  1387.  */
  1388. pascal void aboutDialogOKFrame (WindowPtr theWindow, short itemNo)
  1389. {
  1390.     Rect        r;
  1391.     short        kind;
  1392.     Handle        h;
  1393.     PenState    ps;
  1394.  
  1395.     GetPenState(&ps);
  1396.     GetDialogItem(theWindow, itemNo, &kind, &h, &r);
  1397.     PenSize(3, 3);
  1398.     FrameRoundRect(&r, 16, 16);
  1399.     SetPenState(&ps);
  1400. }
  1401.  
  1402.  
  1403. /* 
  1404.  *    these few lines center the about box to the main screen 1/6 of the way from the bottom of the 
  1405.  *    menubar to the bottom of the main screen.  so decreeth the great John S. 
  1406.  *    noticed the skilled non-use of "with" 
  1407.  */
  1408. void centerDialog(WindowPtr theWindow)
  1409. {
  1410.     short        h, v;
  1411.  
  1412.     #ifdef THINK_C
  1413.         h = (screenBits.bounds.right - screenBits.bounds.left) / 2 - (theWindow->portRect.right - theWindow->portRect.left) / 2;
  1414.         v = (screenBits.bounds.bottom - screenBits.bounds.top) - (theWindow->portRect.bottom - theWindow->portRect.top) - GetMBarHeight();
  1415.     #else
  1416.         h = (qd.screenBits.bounds.right - qd.screenBits.bounds.left) / 2 - (theWindow->portRect.right - theWindow->portRect.left) / 2;
  1417.         v = (qd.screenBits.bounds.bottom - qd.screenBits.bounds.top) - (theWindow->portRect.bottom - theWindow->portRect.top) - GetMBarHeight();
  1418.     #endif
  1419.         v = (v / 3) + GetMBarHeight();
  1420.         
  1421.     /* 
  1422.      *    move the window to the right spot & display it & wait around 
  1423.      */
  1424.     MoveWindow(theWindow, h, v, true);
  1425. }
  1426.  
  1427. /*
  1428.  *     Display the About... dialog.
  1429.  *     Then wait until the OK button is clicked before returning.
  1430.  */
  1431. void showAboutMeDialog(void)
  1432. {
  1433.     GrafPtr     savePort;
  1434.     DialogPtr    aboutDialog;
  1435.     short        itemType;
  1436.     Handle        itemHdl;
  1437.     Rect        itemRect;
  1438.     short        itemHit = 0;
  1439.     UserItemUPP    aboutBoxUPP;
  1440.     
  1441.     GetPort(&savePort);
  1442.     aboutDialog = GetNewDialog(aboutMeDLOG, nil, (WindowPtr) -1);
  1443.     
  1444.     /* 
  1445.      *    set up the userItem proc for the "OK" button outline 
  1446.      */
  1447.     GetDialogItem(aboutDialog, 7, &itemType, &itemHdl, &itemRect);
  1448.     aboutBoxUPP = NewUserItemProc(aboutDialogOKFrame);
  1449.     SetDialogItem(aboutDialog, 7, userItem, (Handle) aboutBoxUPP, &itemRect);
  1450.  
  1451.     centerDialog((WindowPtr) aboutDialog);
  1452.     
  1453.     ShowWindow(aboutDialog);
  1454.     
  1455. #ifdef THINK_C
  1456.     while(itemHit != OK) 
  1457.         ModalDialog(0L, &itemHit);
  1458. #else
  1459.     while(itemHit != ok) 
  1460.         ModalDialog(0L, &itemHit);
  1461. #endif
  1462.  
  1463.     DisposeDialog(aboutDialog);
  1464.  
  1465.     SetPort(savePort);
  1466.  
  1467. #ifdef GENERATINGCFM
  1468.     DisposeRoutineDescriptor(aboutBoxUPP);
  1469. #endif
  1470.  
  1471. } /* showAboutMeDialog */
  1472.  
  1473. void BigBadError(Str255    message)
  1474. {
  1475.     short        itemHit;
  1476.  
  1477.     SetCursor(&qd.arrow);
  1478.     /* type Str255 is an array in MPW 3 */
  1479.     ParamText(message, "\p", "\p", "\p");
  1480.     itemHit = Alert(rUserAlert, nil);
  1481.     closeUpOurAppleTalk();
  1482.     ExitToShell();
  1483. } /* BigBadError */
  1484.  
  1485. /* the following code is from IM VI 3-8 which demonstrates how to check for the 
  1486.  * availability of traps
  1487.  */
  1488.  
  1489. short NumToolboxTraps(void)
  1490. {
  1491.     if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
  1492.         return(0x200);
  1493.     else
  1494.         return(0x400);
  1495.  
  1496. } /* NumToolboxTraps */
  1497.  
  1498. TrapType GetTrapType(short theTrap)
  1499. {
  1500.     short    trapMask = 0x0800;
  1501.     
  1502.     if (theTrap & trapMask)
  1503.         return(ToolTrap);
  1504.     else
  1505.         return(OSTrap);
  1506.  
  1507. } /* GetTrapType */
  1508.  
  1509. Boolean TrapAvailable(short theTrap)
  1510. {
  1511.     TrapType    theType;
  1512.     
  1513.     theType = GetTrapType(theTrap);
  1514.     if (theType == ToolTrap) {
  1515.         theTrap &= 0x07FF;
  1516.         if (theTrap >= NumToolboxTraps())
  1517.             theTrap = _Unimplemented;
  1518.     }
  1519.     return(NGetTrapAddress(theTrap, theType) != NGetTrapAddress(_Unimplemented, ToolTrap));
  1520. }
  1521.  
  1522. /* the following code determines whether VM is active or not
  1523.  * returns false if VM is not on or is not available
  1524.  * returns true if VM is active
  1525.  */
  1526.  
  1527. Boolean IsVMOn(void)
  1528. {
  1529.     long    message;
  1530.     
  1531.     if (!TrapAvailable((short)_Gestalt))
  1532.         return(false);            /* if there is no Gestalt, then VM wont be on */
  1533.         
  1534.     if(Gestalt(gestaltVMAttr, &message))
  1535.         return (false);
  1536.     
  1537.     if (BitTst((Ptr)&message, 31 - gestaltVMPresent))
  1538.         return (true);
  1539.     else
  1540.         return (false);
  1541.     
  1542. } /* IsVMOn */
  1543.  
  1544.